package svg

import (
	"gosvg/dom"
)

type PathElement struct {
	*dom.Element
}

func Path() *PathElement {
	return &PathElement{Element: dom.MakeElementNs("path", SvgNamespace)}
}

func (p *PathElement) pathCmd(cmd string, args ...string) {
	str := cmd
	for i, val := range args {
		if i != 0 {
			str += " "
		}
		str += val
	}

	p.Element.AddToAttribute("d", str)
}

//Move starts a new sub-path at the given absolute coordinates (x,y)
func (p *PathElement) Move(x, y float64) {
	p.pathCmd("M", coords(x, y))
}

//MoveRelative starts a new sub-path at the given relative coordinates (x,y)
func (p *PathElement) MoveRelative(x, y float64) {
	p.pathCmd("m", coords(x, y))
}

//Close closes the current subpath by drawing a straight line 
//from the current point to current subpath's initial point
func (p *PathElement) Close() {
	p.pathCmd("z")
}

//Line draws a line from the current point to the given (x,y) coordinate which 
//becomes the new current point.
func (p *PathElement) Line(x, y float64) {
	p.pathCmd("L", coords(x, y))
}

//Same as Line but relative
func (p *PathElement) LineRelative(x, y float64) {
	p.pathCmd("l", coords(x, y))
}

//HorizontalLine draws a line from the current point (cpx, cpy) to (x, cpy).
func (p *PathElement) HorizontalLine(x float64) {
	p.pathCmd("H", fVal(x))
}

//VerticalLine draws a vertical line from the current point (cpx, cpy) to (cpx, y).
func (p *PathElement) VerticalLine(y float64) {
	p.pathCmd("V", fVal(y))
}

//Same as HorizontalLine but relative value
func (p *PathElement) HorizontalLineRelative(x float64) {
	p.pathCmd("h", fVal(x))
}

//Same as VerticalLine but relative value
func (p *PathElement) VerticalLineRelative(y float64) {
	p.pathCmd("v", fVal(y))
}

//CubicBezier draws a cubic Bézier curve from the current point to (x,y) 
//using (x1,y1) as the control point at the beginning of the curve and 
//(x2,y2) as the control point at the end of the curve.
func (p *PathElement) CubicBezier(x1, y1, x2, y2, x, y float64) {
	p.pathCmd("C", coords(x1, y1), coords(x2, y2), coords(x, y))
}

//Same as CubicBezier but in relative coordinates
func (p *PathElement) CubicBezierRelative(c1x, c1y, c2x, c2y, ex, ey float64) {
	p.pathCmd("c", coords(c1x, c1y), coords(c2x, c2y), coords(ex, ey))
}

//Draws a quadratic Bézier curve from the current point to (x,y) using (x1,y1) 
//as the control point.
func (p *PathElement) QuadraticBezier(c1x, c1y, ex, ey float64) {
	p.pathCmd("Q", coords(c1x, c1y), coords(ex, ey))
}

//Same as QuadraticBezier but relative coordinates
func (p *PathElement) QuadraticBezierRelative(c1x, c1y, ex, ey float64) {
	p.pathCmd("q", coords(c1x, c1y), coords(ex, ey))
}

//Draws an elliptical arc from the current point to (x, y). 
//The size and orientation of the ellipse are defined by two radii (rx, ry) 
//and an x-axis-rotation, which indicates how the ellipse as a whole is rotated 
//relative to the current coordinate system. The center (cx, cy) of the ellipse is 
//calculated automatically to satisfy the constraints imposed by the other parameters. 
//large-arc-flag and sweep-flag contribute to the automatic calculations and help 
//determine how the arc is drawn.
func (p *PathElement) Arc(rx, ry, xAxisRotation float64, largeArc, sweep bool, x, y float64) {
	p.pathCmd("A", coords(rx, ry), fVal(xAxisRotation), comma(boolean(largeArc), boolean(sweep)), coords(x, y))
}

//Same as Arc but in relative coordinates
func (p *PathElement) ArcRelative(rx, ry, xAxisRotation float64, largeArc, sweep bool, x, y float64) {
	p.pathCmd("a", coords(rx, ry), fVal(xAxisRotation), comma(boolean(largeArc), boolean(sweep)), coords(x, y))
}
